package util
{
	import flash.events.Event;
	import flash.events.FileListEvent;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	
	/**
	 * ...
	 * @author WLDragon 2014-02-20
	 */
	public class ParseData
	{
		
		public function ParseData()
		{
			fileInfoList = [];
			fileLoadList = [];
			fileStream = new FileStream();
			urlLoader = new URLLoader();
			urlLoader.addEventListener(Event.COMPLETE, handleLoadComplete);
		}
		
		public function addFeedback(fun:Function):void
		{
			feedback = fun;
		}
		
		/**
		 * 解析并打包数据
		 * @param	sPath      源目录
		 * @param	oFile      输出目录
		 * @param   type       打包类型ParseData.TYPE_DATA|ParseData.TYPE_XML|ParseData.TYPE_MAP
		 * @param	isCreateVO 是否生成值对象文件
		 */
		public function parseAndPackData(sPath:String, oFile:String,type:int, isCreateVO:Boolean = false):void
		{
			if (isWorking)
			{
				feedback.call(null,"正在处理数据，请稍后重试。。。");
			}
			
			curSourcePath = sPath;
			curOutputFile = oFile;
			curType = type;
			this.isCreateVO = isCreateVO;
			
			switch (curType) 
			{
				case TYPE_DATA:
					urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
					break;
				case TYPE_XML:
					urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
					break;
				case TYPE_MAP:
					urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
					sPath = isPackBFile?sPath + "bfile/":sPath + "dfile";
					break;
				default:
			}
				
			//加载文件数据
			var directory:File = new File(sPath);
			if (directory.exists)
			{
				isWorking = true;
				directory.addEventListener(FileListEvent.DIRECTORY_LISTING, handleGetListing);
				directory.getDirectoryListingAsync();
			}
			else
			{
				feedback.call(null,"不存在这个目录");
			}
			
		}
		
		private function handleGetListing(e:FileListEvent):void
		{
			e.target.removeEventListener(FileListEvent.DIRECTORY_LISTING, handleGetListing);
			for each(var f:File in e.files)
			{
				var o:Object = { name:f.name, url:f.url };
				fileLoadList.push(o);
			}
			
			if(fileLoadList.length > 0)loadFile();
		}
		
		private function loadFile():void
		{
			var o:Object = fileLoadList.pop();
			curFileName = o.name.substring(0, o.name.lastIndexOf("."));
			//加载数据
			
			urlLoader.load(new URLRequest(o.url));
		}
		
		private function handleLoadComplete(e:Event):void
		{
			var info:FileInfo = new FileInfo(curFileName, e.target.data);
			fileInfoList.push(info);
			
			if (fileLoadList.length > 0)
			{
				loadFile();
			}
			else
			{
				packData();
			}
		}
			
		private function packData():void
		{
			var bytes:ByteArray = new ByteArray();
			var data:*;
			
			//基于文件循环
			
			while(fileInfoList.length > 0)
			{
				var info:FileInfo = fileInfoList.pop();
				var b:ByteArray = new ByteArray();
				switch (curType) 
				{
					case TYPE_DATA:
						data = parseCustomData(info);
						b.writeUTFBytes(data as String);
					break;
					case TYPE_XML:
						data = info.data;
						b.writeUTFBytes(data as String);
					break;
					case TYPE_MAP:
						data = info.data;
						b.writeBytes(data as ByteArray);
					break;
				}
				
				bytes.writeUTF(info.name);//文件名
				bytes.writeUnsignedInt(b.length);//内容长度
				bytes.writeBytes(b);//内容
			}
			
			saveFile(bytes);
		}
		
		private function parseCustomData(info:FileInfo):String
		{
			var x:XML = new XML(info.data);
			var vo:XML = x.vo[0];
			var data:XML = x.data[0];
			
			var str:String = "";
			var arr:Array = [];
			var prop:XML;
			for each(prop in vo.prop)
			{
				arr.push( { name:prop.@name, type:prop.@type, comment:prop.@comment } );
				//写入字段名
				str += prop.@name + "\t";
			}
			str += "\n";
			for each(prop in vo.prop)
			{
				//写入字段类型
				str += prop.@type + "\t";
			}
			str += "\n";
			
			var len:int = arr.length;
			//基于数据记录循环
			for each(var record:XML in data.record)
			{
				//每条记录的属性循环
				for (var i:int = 0; i < len;i++ )
				{
					//分割字段
					str += record.attributes()[i] + "\t";
				}
				//分割记录
				str += "\n";
			}
			
			if (isCreateVO)
			{
				createVoFile(arr,info.name,vo.@comment);
			}
			
			return str;
		}
		
		private function saveFile(bytes:ByteArray):void
		{
			bytes.compress();
			var path:String;
			if (curType == TYPE_MAP)
			{
				path = isPackBFile?curOutputFile+"maps.b":curOutputFile+"maps.d";
			}
			else
			{
				path = curOutputFile;
			}
			//按输出路径保存文件
			var f:File = new File(path);
			fileStream.open(f,FileMode.WRITE);
			fileStream.writeBytes(bytes);
			fileStream.close();
			
			isWorking = false;
			
			if (curType == TYPE_MAP)
			{
				if (isPackBFile)
				{
					isPackBFile = false;
					parseAndPackData(curSourcePath,curOutputFile,TYPE_MAP);
				}
				else
				{
					isPackBFile = true;
				}
			}
			
			switch (curType) 
			{
				case TYPE_DATA:
					feedback.call(null, "解释游戏数据完成");
				break;
				case TYPE_MAP:
					feedback.call(null, "解释地图数据完成");
				break;
				case TYPE_XML:
					feedback.call(null, "解释XML数据完成");
				break;
			}
		}
		
		private function createVoFile(arr:Array,voName:String,voComment:String):void
		{
			var date:Date = new Date();
			var time:String = date.fullYear + "-" + (date.month + 1) + "-" + date.date;
			var field:String = "";
			for each(var o:Object in arr)
			{
				field += "\t\t/**" + o.comment + "*/\n";
				field += "\t\tpublic var " + o.name + ":" + o.type + ";\n";
			}
			var str:String = voTemplate;
			str = str.replace("#COMMENT",voComment);
			str = str.replace("#TIMESTAMP",time);
			str = str.replace("#CLASSNAME",voName);
			str = str.replace("#FIELDLIST",field);
			
			//生成VO文件
			var f:File = new File("file:///D:/git/BaWangDaLuII/Library/src/vo/" + voName + ".as");
			fileStream.open(f,FileMode.WRITE);
			fileStream.writeUTFBytes(str);
			fileStream.close();
		}
		
		/**是否正在处理数据*/
		private var isWorking:Boolean = false;
		/**是否正在打包地图的B文件*/
		private var isPackBFile:Boolean = true;
		/**等待加载数据的文件列表*/
		private var fileLoadList:Array;
		/**包含文件数据的列表*/
		private var fileInfoList:Array;
		/**当前加载的文件名*/
		private var curFileName:String;
		/**当前打包的文件类型*/
		private var curType:int;
		/**输出的文件名*/
		private var curOutputFile:String;
		/**当前源路径*/
		private var curSourcePath:String;
		/**是否生成VO文件*/
		private var isCreateVO:Boolean;
		/**字节流输出类*/
		private var fileStream:FileStream;
		/**文件加载器*/
		private var urlLoader:URLLoader;
		/**VO文档的模板*/
		private var voTemplate:String = "package vo\n{\n\t/**\n\t* #COMMENT\n\t* @author WLDragon #TIMESTAMP\n\t*/\n\tpublic class #CLASSNAME\n\t{\n#FIELDLIST\t}\n}";
		/**处理结果反馈*/
		private var feedback:Function;
		static public const TYPE_DATA:int = 0;
		static public const TYPE_XML:int = 1;
		static public const TYPE_MAP:int = 2;
	}

}
import flash.utils.ByteArray;


class FileInfo
{
	public function FileInfo(name:String, data:*)
	{
		this.name = name;
		this.data = data;
	}
	
	public var name:String;
	public var data:*;
}